package com.bytefy.server.sandbox;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.util.UUID;
import java.util.logging.Logger;

import org.jgroups.ChannelException;
import org.jgroups.JChannel;

import com.sleepycat.je.Database;
import com.sleepycat.je.DatabaseConfig;
import com.sleepycat.je.DatabaseEntry;
import com.sleepycat.je.Environment;
import com.sleepycat.je.EnvironmentConfig;
import com.sleepycat.je.LockMode;
import com.sleepycat.je.OperationStatus;
import com.sleepycat.je.Transaction;

public class DB {
	private static final String CHARSET = "utf-8";
	private static Environment env;
	private static Database db;
	private static Logger log = Logger.getLogger(DB.class.getName());
	private static String path = "db";
	private static String name = "data";
	private static String id;
	
	static {
		new File(path).mkdir();
		log.info("Starting persistence");
		EnvironmentConfig envConfig = new EnvironmentConfig();
		envConfig.setCachePercent(90);
		envConfig.setTxnNoSync(true);
		envConfig.setAllowCreate(true);
		env = new Environment(new File(path), envConfig);
		DatabaseConfig dbConfig = new DatabaseConfig();
		dbConfig.setDeferredWrite(true);
		dbConfig.setAllowCreate(true);
		db = env.openDatabase(null, name, dbConfig);
		log.info("Started persistence");
		
		final DB db = new DB();
		id = db.get("__id__");
		if (id == null) {
			id = UUID.randomUUID().toString();
			db.put("__id__", id);
			log.info("First start, generate id = "+id);
			db.sync();
		}
		Runtime.getRuntime().addShutdownHook(new Thread() {
			public void run() {
				db.destroy();
			}
		});
		
		JChannel ch;
		try {
			ch = new JChannel();
			ch.connect("bfdb");
		} catch (ChannelException e) {
			e.printStackTrace();
		}
	}

	private static boolean stoped;

	public void put(Object key, Object value, Transaction tx) {
		db.put(tx, toEntry(key.toString()), toEntry(value.toString()));
	}

	public void put(Object key, Object value) {
		this.put(key, value, null);
	}

	public String get(String key) {
		DatabaseEntry valueEntry = new DatabaseEntry();
		OperationStatus status = db.get(null, toEntry(key), valueEntry,
				LockMode.READ_COMMITTED);
		if (!OperationStatus.SUCCESS.equals(status))
			return null;
		return toString(valueEntry);
	}

	public void destroy() {
		stoped = true;
		db.close();
		env.close();
	}
	
	public void sync() {
		log.info("Sync started");
		db.sync();
		log.info("Sync finished");
	}

	private DatabaseEntry toEntry(String d) {
		DatabaseEntry e = null;
		try {
			e = new DatabaseEntry(d.getBytes(CHARSET));
		} catch (UnsupportedEncodingException ex) {
			ex.printStackTrace();
		}
		return e;
	}

	private String toString(DatabaseEntry e) {
		String s = null;
		try {
			s = new String(e.getData(), CHARSET);
		} catch (UnsupportedEncodingException ex) {
			ex.printStackTrace();
		}
		return s;
	}
}

class ArrayEntry {
	public String prev;
	public String next;
	public String value;

	@Override
	public String toString() {
		StringBuilder b = new StringBuilder();
		b.append(prev);
		b.append("_");
		b.append(next);
		b.append("_");
		b.append(value);
		return b.toString();
	}
}